<?php

#<editor-fold defaultstate="collapsed" desc="CCore::Using">
CCore::Using('db.inc.abstract');
CCore::Using('db.mysql.config');
CCore::Using('base.developments');
#</editor-fold>

class CCoreDbMysql extends ACoreDb
{
	#<editor-fold defaultstate="collapsed" desc="constants">
	const FETCH_TYPE_ARRAY	= 0;
	const FETCH_TYPE_OBJECT	= 1;
	#</editor-fold>
	
	/**
	 * @param	CCoreDbMySqlConfig	$oCoreMySqlConfig
	 * @param	array				$aFollowers = array()
	 * @return	CCoreDbMysql
	 */
	public function __construct(CCoreDbMySqlConfig $oCoreMySqlConfig, $aFollowers = array())
	{
		CCore::CheckTypes(array('$oCoreMySqlConfig', '$noInputLogger'));
		
		$oDevelopments = new CCoreBaseDevelopments('MySQL', 'MySQL[Error]', 'MySQL[Warning]', 'MySQL[Notice]');
		$oDevelopments->AddArray($aFollowers);

		parent::__construct($oCoreMySqlConfig, $oDevelopments);
	}

	/**
	 * @return	void
	 */
	function  __destruct()
	{
		$this->Disconnect();
	}
	
	/**
	 * @param	bool	$bSelectDataBase = true
	 * @return	bool
	 */
	public function Connect($bSelectDataBase = true)
	{
		CCore::CheckTypes(array('$bSelectDataBase'));
		
		if (!extension_loaded('mysql'))
		{
			$this->oDevelopments->Write('extension MySQL not loaded', CCoreBaseDevelopments::ERROR);
			return false;
		}
		
		$sHost = $this->oConfig->GetValue('Host', 'string');
		$sLogin = $this->oConfig->GetValue('Login', 'string');
		$sPassword = $this->oConfig->GetValue('Password', 'string');
		
		$this->oDevelopments->Write('start connect to '.$sHost.'@'.$sLogin, CCoreBaseDevelopments::INFO);
		$this->rConnect = @mysql_connect($sHost, $sLogin, $sPassword);
		if ($this->IsConnected())
		{
			return ($bSelectDataBase) ? $this->SelectDataBase() : true;
		}
		else
		{
			$this->_initError();
			return false;
		}
	}
	
	/**
	 * @return	bool
	 */
	public function SelectDataBase()
	{
		if ($this->IsConnected())
		{
			$sDataBaseName = $this->oConfig->GetValue('DataBaseName', 'string');
			if (strlen($sDataBaseName) > 0)
			{
				$bDbNameSelect = @mysql_select_db($sDataBaseName, $this->rConnect);
				if (!$bDbNameSelect)
				{
					$this->_initError();
					$this->Disconnect();					
					return false;
				}
			}
			return true;
		}
	}
	
	/**
	 * @return	true
	 */
	public function Disconnect()
	{
		$this->FreeResult();
		if ($this->rConnect)
		{
			$sHost = $this->oConfig->GetValue('Host', 'string');
			$sLogin = $this->oConfig->GetValue('Login', 'string');

			$this->oDevelopments->Write('diconnect from '.$sHost.'@'.$sLogin, CCoreBaseDevelopments::INFO);
			@mysql_close($this->rConnect);
		}
		$this->rConnect = null;
		return true;
	}
	
	/**
	 * @param	string	$sSql
	 * @return	resource | false
	 */
	public function Query($sSql)
	{
		CCore::CheckTypes(array('$sSql'));
		
		if (!$this->IsConnected() && !$this->Connect())
		{
			return false;
		}

		$this->oDevelopments->Write($sSql, CCoreBaseDevelopments::INFO);

		$this->rResult = @mysql_query($sSql, $this->rConnect);
		if (false === $this->rResult)
		{
			$this->_initError();
		}
		
		return $this->rResult;
	}
	
	/**
	 * @return	object | false | null
	 */
	public function GetNextObject()
	{
		return ($this->rResult) ? @mysql_fetch_object($this->rResult) : null;
	}

	/**
	 * @return	array | false | null
	 */
	public function GetNextArray()
	{
		return ($this->rResult) ? @mysql_fetch_assoc($this->rResult) : null;
	}

	/**
	 * @param	int		$iType = self::FETCH_TYPE_OBJECT
	 * @return	array
	 */
	public function GetRecords($iType = self::FETCH_TYPE_OBJECT)
	{
		CCore::CheckTypes(array('$iType'));
		
		$aReturn = array();

		if ($this->rResult)
		{
			$mRow = null;
			$sFunctionName = 'GetNextObject';
			switch ($iType)
			{
				case self::FETCH_TYPE_ARRAY:
					$sFunctionName = 'GetNextArray';
					break;
			}
			while (null != ($mRow = call_user_func(array(&$this, $sFunctionName))))
			{
				$aReturn[] = $mRow;
			}
		}
		return $aReturn;
	}

	/**
	 * @return	int | false
	 */
	public function GetLastInsertId()
	{
		$iReturn = @mysql_insert_id($this->rConnect);
		return ($iReturn > 0) ? $iReturn : false;
	}

	/**
	 * @return	int | false
	 */
	public function GetAffectedRows()
	{
		$iReturn = @mysql_affected_rows($this->rConnect);
		return ($iReturn > -1) ? $iReturn : false;
	}
	
	/**
	 * @return	int | false
	 */
	public function ResultCount()
	{
		return @mysql_num_rows($this->rResult);
	}
	
	/**
	 * @return	bool
	 */
	public function TBegin()
	{
		return (false !== $this->Query('BEGIN'));
	}

	/**
	 * @return	bool
	 */
	public function TCommit()
	{
		return (false !== $this->Query('COMMIT'));
	}

	/**
	 * @return	bool
	 */
	public function TRollBack()
	{
		return (false !== $this->Query('ROLLBACK'));
	}

	/**
	 * @param	string	$sName
	 * @return	string
	 */
	public function QuoteName($sName)
	{
		CCore::CheckTypes(array('$sName'));
		
		return '`'.$sName.'`';
	}

	/**
	 * @param	string	$sValue
	 * @return	string
	 */
	public function QuoteString($sValue)
	{
		CCore::CheckTypes(array('$sValue'));
		
		if ($sValue === '' || $sValue === null)
		{
			return "''";
		}
		
		return '\''.addslashes($sValue).'\'';
	}
	
	/**
	 * @param	string	$sValue
	 * @return	string
	 */
	public function QuoteBin($sValue)
	{
		CCore::CheckTypes(array('$sValue'));

		return $this->QuoteString($sValue);
	}

	/**
	 * @param	string	$sFieldName
	 * @return	string
	 */
	public function SelectDateFormat($sFieldName)
	{
		CCore::CheckTypes(array('$sFieldName'));

		return 'DATE_FORMAT('.$sFieldName.', "%Y-%m-%d %T") as '.$sFieldName;
	}

	/**
	 * @return	void
	 */
	public function FreeResult()
	{
		if ($this->rResult)
		{
			@mysql_free_result($this->rResult);
		}
		
		$this->rResult = null;
	}

	/**
	 * @return	void
	 */
	public function _initError()
	{
		$sErrorDesc = '';
		$iErrorNo = 0;
		
		if (is_resource($this->rConnect))
		{
			$sErrorDesc = @mysql_error($this->rConnect);
			$iErrorNo = @mysql_errno($this->rConnect);
		}
		else
		{
			$sErrorDesc = @mysql_error();
			$iErrorNo = @mysql_errno();
		}
		
		if (strlen($sErrorDesc) > 0 || $iErrorNo > 0)
		{
			$sErrorDesc = (strlen($sErrorDesc) > 0) ? $sErrorDesc : 'no error occurred';
			$sErrorDesc .= ($iErrorNo > 0) ? ' [code '.$iErrorNo.']' : '';

			$this->oDevelopments->Write($sErrorDesc, CCoreBaseDevelopments::ERROR);
		}
	}
}
